package com.zhizhi.auth;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zhizhi.domain.AccountBO;
import com.zhizhi.domain.RequestTokenBO;
import com.zhizhi.module.synthesizes.account.entity.AccountRoleRel;
import com.zhizhi.module.synthesizes.account.service.AccountRoleRelService;
import com.zhizhi.module.synthesizes.account.service.AccountService;
import com.zhizhi.module.synthesizes.resources.entity.Resources;
import com.zhizhi.module.synthesizes.resources.service.ResourcesService;
import com.zhizhi.module.synthesizes.role.entity.Role;
import com.zhizhi.module.synthesizes.role.entity.RoleResourcesRel;
import com.zhizhi.module.synthesizes.role.service.RoleResourcesRelService;
import com.zhizhi.module.synthesizes.role.service.RoleService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 功能描述: shiro自定义Realm
 * @author Mr.Yu
 * @date 2021/3/31
 */
@Component
public class AuthRealm extends AuthorizingRealm {

    @Autowired
    AccountService accountService;

    @Autowired
    RoleService roleService;

    @Autowired
    ResourcesService resourcesService;

    @Autowired
    AccountRoleRelService accountRoleRelService;

    @Autowired
    RoleResourcesRelService roleResourcesRelService;


    @Override
    /**
     * 授权 获取用户的角色和权限
     *@param  [principals]
     *@return org.apache.shiro.authz.AuthorizationInfo
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //1. 从 PrincipalCollection 中来获取登录用户的信息
        AccountBO user = (AccountBO) principals.getPrimaryPrincipal();
        Integer userId = user.getId();
        //查询对应角色
        QueryWrapper<AccountRoleRel> accountRoleRelQueryWrapper = new QueryWrapper<>();
        accountRoleRelQueryWrapper.lambda().eq(AccountRoleRel::getUserId,userId);
        List<AccountRoleRel> accountRoleRelList = accountRoleRelService.list(accountRoleRelQueryWrapper);
        List<Integer> roleIdList = accountRoleRelList.stream().map(AccountRoleRel::getRoleId).collect(Collectors.toList());
        if(roleIdList.size()==0){
            roleIdList.add(-100);
        }
        List<Role> roleList = roleService.getByIds(roleIdList);

        //查询对应的权限
        QueryWrapper<RoleResourcesRel> roleResourcesRelQueryWrapper = new QueryWrapper<>();
        roleResourcesRelQueryWrapper.lambda().in(RoleResourcesRel::getRoleId,roleIdList);
        List<RoleResourcesRel> roleResourcesRelList = roleResourcesRelService.list(roleResourcesRelQueryWrapper);
        List<Integer> resourcesIdList = roleResourcesRelList.stream().map(RoleResourcesRel::getResourceId).collect(Collectors.toList());
        if(resourcesIdList.size()==0){
            resourcesIdList.add(-100);
        }
        List<Resources> resourcesList = resourcesService.getByIds(resourcesIdList);


        //2.添加角色和权限
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        roleList.forEach(item->{
            simpleAuthorizationInfo.addRole(item.getName());
        });

        resourcesList.forEach(item->{
            simpleAuthorizationInfo.addStringPermission(item.getSelfKey());
        });


//        for (Role role : user.getRoles()) {
//            //2.1添加角色
//            simpleAuthorizationInfo.addRole(role.getRoleName());
//            for (Permission permission : role.getPermissions()) {
//                //2.1.1添加权限
//                simpleAuthorizationInfo.addStringPermission(permission.getPermission());
//            }
//        }
        return simpleAuthorizationInfo;
    }

    @Override
    /**
     * 认证 判断token的有效性
     *@param  [token]
     *@return org.apache.shiro.authc.AuthenticationInfo
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //获取token，既前端传入的token
        String accessToken = (String) token.getPrincipal();
        //1. 根据accessToken，查询用户信息
        RequestTokenBO requestTokenBO =  accountService.getAccountByToken(accessToken);
        //2. token失效
        if(ObjectUtil.isNull(requestTokenBO)){
            throw new IncorrectCredentialsException("token失效，请重新登录");
        }

        //5. 根据用户的情况, 来构建 AuthenticationInfo 对象并返回. 通常使用的实现类为: SimpleAuthenticationInfo
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(requestTokenBO.getAccountBO(), accessToken, this.getName());
        return info;
    }
}
